package cn.hejiang.mamis.web.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.hejiang.mamis.core.dto.ResultDTO;
import cn.hejiang.mamis.core.entity.PlatSys;
import cn.hejiang.mamis.core.entity.PlatUser;
import cn.hejiang.mamis.core.entity.SessionDetails;
import cn.hejiang.mamis.core.entity.SysMenu;
import cn.hejiang.mamis.core.entity.SysPage;
import cn.hejiang.mamis.core.service.ContextService;
import cn.hejiang.mamis.core.service.PlatSysService;
import cn.hejiang.mamis.core.service.SysMenuService;
import cn.hejiang.mamis.core.service.SysPageService;
import cn.hejiang.mamis.core.util.EntityUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

@Controller
@RequestMapping("/mamis")
@Slf4j
public class PageController {
	@Autowired
	ContextService contextService;

	@Autowired
	SysMenuService sysMenuService;

	@Autowired
	SysPageService sysPageService;

	@Autowired
	PlatSysService platSysService;

	@Value("${web.proxy.context-path:}")
	String webProxyContextPath;
	
	private String getContextPath(HttpServletRequest request) {
		if (StrUtil.isNotBlank(webProxyContextPath)) {
			String ctx = webProxyContextPath.trim();
			return ctx.endsWith("/") ? ctx.substring(0, ctx.length() - 1) : ctx;
		}
		
		return request.getContextPath();
	}

	@GetMapping("/")
	public String home(HttpServletRequest request, HttpServletResponse response, Model model) {
		SessionDetails session = contextService.getSession(request);

		try {
			contextService.getSystem();
		} catch (Exception e) {
			log.warn("{} - 重定向到平台首页: {}", e.getLocalizedMessage(), request.getContextPath() + "/mamis");
			try {
				response.sendRedirect(request.getContextPath() + "/mamis");
			} catch (IOException e1) {
				log.error(e1.getLocalizedMessage(), e1);
			}
			return null;
		}

		PlatSys sys = platSysService.getSysById(contextService.getSystem().getId());

		model.addAttribute("sysCode", sys.getCode());
		model.addAttribute("appName", sys.getName());
		model.addAttribute("appLogo", sys.getLogo());
		model.addAttribute("appHeader", sys.getHeader());
		model.addAttribute("appFooter", sys.getFooter());
		model.addAttribute("appFavicon", sys.getFavicon());

		PlatUser user = session.getCurUser();
		model.addAttribute("username", user.getName());
		model.addAttribute("loginName", user.getLoginName());

		model.addAttribute("contextPath", getContextPath(request));

		return "app";
	}

	@GetMapping("/preview/{pageId}")
	public String page(HttpServletRequest request, @RequestParam("sysCode") String sysCode,
			@PathVariable("pageId") String pageId, Model model) {
		contextService.setSystemByCode(sysCode);
		PlatSys sys = platSysService.getSysById(contextService.getSystem().getId());

		model.addAttribute("sysCode", sys.getCode());
		model.addAttribute("js", "/mamis/pages/" + pageId + ".js?_t=" + new Date().getTime() + "&sysCode=" + sysCode);

		model.addAttribute("contextPath", getContextPath(request));

		return "page";
	}

	@GetMapping("/editor/{pageId}")
	public String editor(HttpServletRequest request, @RequestParam("sysCode") String sysCode,
			@PathVariable("pageId") String pageId, Model model) {
		contextService.setSystemByCode(sysCode);
		PlatSys sys = platSysService.getSysById(contextService.getSystem().getId());
		long time = new Date().getTime();

		model.addAttribute("sysCode", sys.getCode());
		model.addAttribute("js", "/mamis/pages/" + pageId + ".js?_t=" + time + "&sysCode=" + sysCode);
		model.addAttribute("pageId", pageId);

		model.addAttribute("contextPath", getContextPath(request));

		return "editor";
	}

	@GetMapping("/pages/{pageId}.js")
	@ResponseBody
	public String pageJS(HttpServletRequest request, @RequestParam("sysCode") String sysCode,
			@PathVariable("pageId") String pageId, @RequestParam Map<String, Object> data) {
		contextService.setSystemByCode(sysCode);
		// 从当前组织下获取页面
		SysPage page = sysPageService.getPageById(pageId, contextService.getSystem().getId());
		String content = page.getContent();
		JSONObject json = JSONUtil.parseObj(content);

		// 使用查询参数数据覆盖 json 中配置的数据
//		if (json.containsKey("data")) {
//			JSONObject oldData = json.getJSONObject("data");
//			oldData.putAll(data);
//			json.set("data", oldData);
//		} else {
//			json.set("data", data);
//		}

		// 返回 js 文件内容
		return "window.amisJSON = " + JSONUtil.toJsonPrettyStr(json);
	}

	@GetMapping("/pages/site.json")
	@ResponseBody
	public Object siteJSON(HttpServletRequest request) {
		final SessionDetails session = contextService.getSession(request);

		// 查询菜单列表
		List<SysMenu> menuList = sysMenuService.getUserMenuList(session.getCurUserId(), session.getCurDeptId(),
				contextService.getSystem().getId());
		List<SysMenu> menuTree = EntityUtil.plainToTree(menuList);

		// 构造页面列表
		PlatSys sys = platSysService.getSysById(contextService.getSystem().getId());
		List<Map<String, Object>> pageList = buildPageList(menuTree, sys.getHome(), getContextPath(request),
				contextService.getSystem().getCode(), new Date().getTime());

		// 返回 site.json
		Map<String, Object> ret = new HashMap<>();
		ret.put("pages", pageList);

		return ResultDTO.success(ret);
	}

	@GetMapping("/pages/{pageId}.json")
	@ResponseBody
	public String pageJSON(HttpServletRequest request, @RequestParam("sysCode") String sysCode,
			@PathVariable("pageId") String pageId) {
		contextService.setSystemByCode(sysCode);
		// 从当前组织下获取页面
		SysPage page = sysPageService.getPageById(pageId, contextService.getSystem().getId());
		return page.getContent();
	}

	private List<Map<String, Object>> buildPageList(List<SysMenu> menuList, String homeUrl, String contextPath,
			String sysCode, long time) {
		List<Map<String, Object>> pages = new ArrayList<>();

		// 菜单页面组
		Map<String, Object> menuPage = new HashMap<>();
		pages.add(menuPage);

		// 菜单列表
		List<Map<String, Object>> menus = new ArrayList<>();
		menuPage.put("children", menus);

		// 添加菜单项
		for (SysMenu item : menuList) {
			menus.add(buildMenuItem(item, contextPath, sysCode, time));
		}

		Map<String, Object> homePage = new HashMap<>();
		pages.add(homePage);

		homePage.put("label", "/"); // 有 / 后缀跳转
		homePage.put("url", contextPath + "/" + sysCode + "/");
		homePage.put("redirect", contextPath + "/" + sysCode);

		homePage = new HashMap<>();
		pages.add(homePage);

		homePage.put("label", ""); // 无 / 后缀跳转
		homePage.put("url", contextPath + "/" + sysCode);

		// 指定登录后跳转页面
		if (StrUtil.isBlank(homeUrl) || "/".equals(homeUrl)) {
			// 未设置或无效设置
			if (menus.size() == 0) {
				// 没有菜单访问权限，直接返回
				return pages;
			}
			homePage.put("redirect", (String) menus.get(0).get("url"));
		} else if (homeUrl.startsWith("/")) {
			// 绝对路径
			homePage.put("redirect", contextPath + "/" + sysCode + homeUrl);
		} else {
			// 相对路径，一般不存在这种设置
			homePage.put("redirect", homeUrl); // 首页 url
		}

		return pages;
	}

	private Map<String, Object> buildMenuItem(SysMenu item, String contextPath, String sysCode, long time) {
		Map<String, Object> page = new HashMap<>();

		page.put("label", item.getName());
		page.put("icon", item.getIcon());
		if (StrUtil.isNotBlank(item.getUrl()) && item.getUrl().startsWith("/")) {
			page.put("url", contextPath + "/" + sysCode + item.getUrl());
		} else {
			page.put("url", item.getUrl());
		}

		List<Map<String, Object>> children = new ArrayList<Map<String, Object>>();
		if (item.getChildren() != null) {
			for (SysMenu subItem : item.getChildren()) {
				children.add(buildMenuItem(subItem, contextPath, sysCode, time));
			}

			if (StrUtil.equals("/dev", item.getUrl())) {
				Map<String, Object> editor = new HashMap<>();

				editor.put("label", "页面编辑器");
				editor.put("url", contextPath + "/" + sysCode + "/dev/editor");
				editor.put("visible", false);
				editor.put("schemaApi", "/amis/pages/dev-editor.json?_t=" + time + "&sysCode=" + sysCode);

				children.add(editor);
			}
		}

		if (children.size() > 0) {
			page.put("children", children);
			page.put("redirect", children.get(0).get("url"));
		} else {
			if (item.getType() == SysMenu.TYPE_STATIC_PAGE) {
				page.put("schemaApi", "/amis/pages/" + item.getPageId() + ".json?_t=" + time + "&sysCode=" + sysCode);
			} else if (item.getType() == SysMenu.TYPE_DYNAMIC_PAGE) {
				page.put("schemaApi", "/mamis/pages/" + item.getPageId() + ".json?_t=" + time + "&sysCode=" + sysCode);
			}
		}

		return page;
	}
}
